Skip to main content

Basic structure of an OI4 OEC service

The oi4-oec-service is intended to cover as much of the OI4 OEC state machine as possible. By just creating an instance of the IOI4Application and providing the according configuration you will receive an (almost) OI4 OEC compliant application. Of course, this application will not provide any useful information. The oi4-oec-service offers a couple of Interfaces and according default implementations. Those default implementations are intended to be overridden to provide the application specific logic.

But we will come to all of that later...first things first.

The simplest OI4 OEC application

const applicationResources = new OI4ApplicationResources();
new OI4ApplicationFactory(applicationResources).build();

The provided code snipped will create an instance of the IOI4ApplicationResources with the help of the default implementation OI4ApplicationResources. It assumes that the configuration is provided as described in Configuration of OEC services and a that there is a JSON file describing the MAM of the service present at /etc/oi4/config/mam.json. Not bad, right? But again, this service will not provide any useful information. But before we dive into details how to provide your own business logic and information, we will cover all major Interfaces, Classes, etc. that you should be aware of.

Overview of major Interfaces, Classes, etc.

IOI4Application - The core of an OI4 application

The Interface IOI4Application contains most of the business logic that is needed by the OI4 state machine. It will set up the MQTT connection, send the birth message, register the LWT message and subscribe to the relevant topics. It will also send the periodic health state. Furthermore, it offers a couple of methods to send messages to the broker.

The provided default implementation is the Class OI4Application. Typically, the default implementation should work. In case you need to publish data regularly, e.g. if you provide an OT Connector, you can extend this class and add the publishing with a setInterval. An example how to do that is available in the ServiceDemoOI4Application of the demo service.

Foreign messages

Sending an according response message to a GET request is handled by the oi4-service out of the box. If your application is subscribed an Event with the symbol foreignMessage is emitted by the MqttMessageProcessor. The IOI4Application offers an addListener and removeListener function that can be used to un/-subscribe to these events...

import {foreignMessage} from '../messaging/MqttMessageProcessor';

const application = new OI4ApplicationFactory(applicationResources, paths).initialize(builder).createOI4Application();
const listener = (topicInfo: TopicInfo, parsedMessage: IOPCUANetworkMessage): void => {
console.log(`Topic: ${topicInfo} Message: ${parsedMessage}`)
};
application.addListener(foreignMessage, listener)
application.removeListener(foreignMessage, listener)

IOI4ApplicationResources - The data provider

The Interface IOI4ApplicationResources it the pivotal data provider. Whenever an OI4 resource is requested (meaning a GET message has been received) the IOI4Application will retrieve the data from the IOI4ApplicationResources. The default implementation is OI4ApplicationResources, but the class is meant to be overridden in case your service provides data. Your implementation should override the getters and setters of the individual properties.

The IOI4ApplicationResources is derived from the Interface IOI4Resource, respectively OI4Resource. An IOI4Resource is equivalent to Source in the OI4 OEC specification. It can be the application/service itself or an affiliated asset.

IOI4ApplicationFactory - The starting point

The Interface IOI4ApplicationFactory and its implementation the OI4ApplicationFactory are the starting point for every OI4 application. The factory processes the configurations and create an instance of the IOI4Application. If you stay with the default settings paths, you just have to provide an IOI4ApplicationResources of your application.

Typical starting points

The oi4-service has the intention to make your life with OI4 easier. Therefore, there is not that much to do, to get your application up and running. The Classes you will have to implement differ a bit, depending on the nature of your service. Either you provide data to the bus (e.g. an OT Connector), consume data from bus (e.g. a cloud connector) or you do both. Here are examples for the different cases.

OT Connector providing data

  • Extend the Class OI4ApplicationResources to provide access to the assets (as SubResources). Here is an example for such a class.
  • Create an instance of your OI4ApplicationResources.
  • Extend the Class OI4Application to frequently provide your data like in this example.
  • Extend the Class OI4ApplicationBuilder and override the method newOI4Application to return an instance of your OI4Application implementation; CLICK
  • Initialize the OI4ApplicationFactory with your OI4ApplicationResources and builder... const applicationFactory = new OI4ApplicationFactory(applicationResources).initialize(builder);
  • Finally, create the OI4Application with... applicationFactory.createOI4Application();

OOCConnector consumer data

  • Create an instance of OI4ApplicationResources.
  • Add listener to the foreignMessage event.
  • Add your additional subscriptions (in this example all MAM messages).
const applicationResources = new OI4ApplicationResources();
const application = new OI4ApplicationFactory(applicationResources, paths).initialize(builder).createOI4Application();
const listener = (topicInfo: TopicInfo, parsedMessage: IOPCUANetworkMessage): void => {
console.log(`Topic: ${topicInfo} Message: ${parsedMessage}`)
};
application.addListener(foreignMessage, listener)
await application.addSubscription('Oi4/OTConnector/+/+/+/+/Pub/MAM');
await application.addSubscription('Oi4/OTConnector/+/+/+/+/Pub/MAM/*');